home *** CD-ROM | disk | FTP | other *** search
/ PD Collection CD 1 / PD Collection CD 1.iso / programer2 / euclidlib / c / function < prev    next >
Text File  |  1992-04-19  |  3KB  |  90 lines

  1. /**** function.c ****/
  2. /* By Paul Field
  3.  * See !ReadMe file for distribution/modification restrictions
  4.  */
  5.  
  6. #include "function.h"
  7. #include <float.h>
  8. #include <stdio.h>
  9.  
  10. #define max(a,b) ((a)>(b)?(a):(b))
  11. #define min(a,b) ((a)<(b)?(a):(b))
  12.  
  13.  
  14. static os_error memerr = { 0, "Not enough memory - increase wimpslot." };
  15.  
  16.  
  17. /* Points on the graph are (X,Y,f(X,Y))
  18.  */
  19.  
  20. os_error *function_makegraph(euclid_header *h, graphdata *g, euclid_mesh **mesh)
  21.  { double *results, *r;
  22.    double minz,maxz;              /* Maximum and minimum of the function */
  23.    double rangex,rangey,rangez;
  24.    double maxrange;
  25.    double scale;
  26.    double dy,dx;                  /* Change in function variables per square */
  27.    double fx,fy;                  /* Function variables */
  28.    int ax,ay;                     /* 'results' array indices */
  29.    os_error *e;
  30.  
  31.    results = malloc((g->subdivisions+1)*(g->subdivisions+1)*sizeof(double));
  32.    if (results == NULL)
  33.     { return(&memerr);
  34.     }
  35.    rangex = g->maxx-g->minx;
  36.    rangey = g->maxy-g->miny;
  37.    dx = rangex/g->subdivisions;
  38.    dy = rangey/g->subdivisions;
  39.    minz = DBL_MAX;
  40.    maxz = DBL_MIN;
  41.    r = results;
  42.  
  43.    /* I'm using ax and ay because there may be rounding errors  */
  44.    /* and other problems with fx and fy if dx and dy are small. */
  45.    for (ax = 0, fx = g->minx; ax <= g->subdivisions; ax++, fx += dx)
  46.     { for (ay = 0, fy = g->miny; ay <= g->subdivisions; ay++, fy += dx)
  47.        { *r = g->f(fx,fy);
  48.          maxz = max(*r,maxz);
  49.          minz = min(*r,minz);
  50.          r++;
  51.        }
  52.     }
  53.    rangez = maxz-minz;
  54.    maxrange = max(rangex, rangey);
  55.    maxrange = max(maxrange, rangez);
  56.    scale = g->realsize/maxrange;
  57.  
  58.    if ((e = euclid_create(g->subdivisions+1, h, eid_mesh, mesh)) == NULL)
  59.     { euclid_setname((*mesh)->name, g->name);
  60.       r = results;
  61.       for (ax = 0, fx = g->minx; ax <= g->subdivisions && !e; ax++, fx += dx)
  62.        { euclid_vane *v;
  63.  
  64.          if ((e = euclid_create(g->subdivisions+1, h, eid_vane, &v)) == NULL)
  65.           { (*mesh)->var[ax].colour.c.abscolour = euclid_makecolour(0x80u,0,0,0);
  66.             (*mesh)->var[ax].vane = v;
  67.             for (ay = 0, fy = g->miny; ay <= g->subdivisions; ay++, fy += dx)
  68.              { struct euclid_vanevar *vv;
  69.  
  70.                vv = &v->var[ay];
  71.                vv->colour1.c.abscolour = euclid_makecolour(0x80u,0xff,0xff,0xff);
  72.                vv->colour2.c.abscolour = euclid_makecolour(0x80u,0xff,0xff,0xff);
  73.                vv->point.x = (int)((fx-g->minx-rangex/2)*scale+0.5);
  74.                vv->point.y = (int)((fy-g->miny-rangey/2)*scale+0.5);
  75.                vv->point.z = (int)((*r++)*scale+0.5);
  76.              }
  77.           }
  78.        }
  79.       if (e)
  80.        { for (ax--; ax >= 0; ax--)
  81.           { euclid_destroy(h, (*mesh)->var[ax].vane);
  82.           }
  83.          euclid_destroy(h, *mesh);
  84.        }
  85.     }
  86.    g->scale = scale;
  87.    free(results);
  88.    return(e);
  89.  }
  90.